package edu.neusoft.yiqibike.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import edu.neusoft.yiqibike.common.entity.AdminRole;
import edu.neusoft.yiqibike.common.entity.RolePermission;
import edu.neusoft.yiqibike.common.entity.convert.*;
import edu.neusoft.yiqibike.common.entity.mysql.Admin;
import edu.neusoft.yiqibike.common.entity.mysql.Permission;
import edu.neusoft.yiqibike.common.entity.mysql.Role;
import edu.neusoft.yiqibike.common.entity.vo.AuthoRangeVo;
import edu.neusoft.yiqibike.common.entity.vo.TreeVo;
import edu.neusoft.yiqibike.common.util.CommonUtil;
import edu.neusoft.yiqibike.dao.mapper.AdminRoleMapper;
import edu.neusoft.yiqibike.dao.mapper.RolePermissionMapper;
import edu.neusoft.yiqibike.service.IAdminService;
import edu.neusoft.yiqibike.service.IAuthorizationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * User：lyc
 * Date：2017-12-30
 * Time：14:12
 * Description：
 */
@Service
public class AuthorizationServiceImpl implements IAuthorizationService {
    @Autowired
    private IAdminService adminService;
    @Autowired
    private AdminRoleMapper adminRoleMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    /**
     * 获取权限数据
     *
     * @param aid 管理员ID
     * @return
     */
    @Override
    public TreeVo getTreeList(Long aid) {
        Admin admin = adminService.getAdminById(aid);
        AdminConverter adminConverter = new AdminConverter();
        TreeVo ownerVo = adminConverter.toDto(admin);
        List<TreeVo> roleVoList = new ArrayList<>();
        List<AdminRole> adminRoles = new AdminRole().selectList(new EntityWrapper().eq("aid", aid));
        Set<Long> rids = adminRoles.stream().map(AdminRole::getRid).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(rids)) {
            List<Role> roles = new Role().selectList(new EntityWrapper().in("id", rids));
            roles = roles.stream().sorted(Comparator.comparingInt(Role::getLevel).reversed()).collect(Collectors.toList());
            RoleConverter roleConverter = new RoleConverter();
            List<TreeVo> roleDtos = roleConverter.toDtoList(roles);
            for (TreeVo roleVo : roleDtos) {
                if (Objects.nonNull(roleVo)) {
                    List<RolePermission> rolePermissions = new RolePermission().selectList(
                            new EntityWrapper().eq("rid", roleVo.getId()));
                    Set<Long> pids = rolePermissions.stream().map(RolePermission::getPid).collect(Collectors.toSet());
                    if (!CollectionUtils.isEmpty(pids)) {
                        List<Permission> permissions = new Permission().selectList(
                                new EntityWrapper().in("id", pids));
                        permissions = permissions.stream().sorted(Comparator.comparingInt(Permission::getLevel).reversed())
                                .collect(Collectors.toList());
                        PermissionConverter permissionConverter = new PermissionConverter();
                        List<TreeVo> permissionVos = permissionConverter.toDtoList(permissions);
                        roleVo.setChildren(permissionVos);
                    }
                    roleVoList.add(roleVo);
                }
            }
        }
        ownerVo.setChildren(roleVoList);
        return ownerVo;
    }

    /**
     * 添加角色
     *
     * @param aid    管理员ID
     * @param roleVo 角色代码
     * @param admin  当前登录的管理员
     * @return
     */
    @Override
    @Transactional
    public Long addRole(Long aid, TreeVo roleVo, Admin admin) {
        String creator = null;
        if (Objects.nonNull(admin)) {
            creator = admin.getRealname();
        }
        Date now = new Date();
        RoleConverter roleConverter = new RoleConverter();
        Role role = roleConverter.toEntity(roleVo);
        Role dbRole = role.selectOne(new EntityWrapper().eq("code", role.getCode()));
        if (dbRole == null) {
            role.setCreateTime(now);
            role.setLastModifyTime(now);
            role.setCreator(creator);
            role.setLastModifier(creator);
            role.insert();
        } else {
            role = dbRole;
        }

        List<AdminRole> dbAdminRole = adminRoleMapper.selectRolesByAid(aid);
        if (CollectionUtils.isEmpty(dbAdminRole)) {
            AdminRole adminRole = new AdminRole();
            adminRole.setAid(aid);
            adminRole.setCreateTime(now);
            adminRole.setCreator(creator);
            adminRole.setLastModifier(creator);
            adminRole.setLastModifyTime(now);
            adminRole.setRid(role.getId());
            adminRole.insert();
        } else {
            for (AdminRole adminRole : dbAdminRole) {
                adminRoleMapper.updateByIdAndIsEnable(adminRole.getId(), 1, now, creator);
            }
        }
        return role.getId();
    }

    /**
     * 添加权限
     *
     * @param rid          角色ID
     * @param permissionVo 权限代码
     * @param admin        当前登录的管理员
     * @return
     */
    @Override
    @Transactional
    public Long addPermission(Long rid, TreeVo permissionVo, Admin admin) {
        Date now = new Date();
        String creator = null;
        if (Objects.nonNull(admin)) {
            creator = admin.getRealname();
        }
        PermissionConverter permissionConverter = new PermissionConverter();
        Permission permission = permissionConverter.toEntity(permissionVo);
        Permission dbPermission = permission.selectOne(new EntityWrapper().eq("code", permission.getCode()));
        if (null == dbPermission) {
            permission.setCreateTime(now);
            permission.setLastModifyTime(now);
            permission.setCreator(creator);
            permission.setLastModifier(creator);
            permission.insert();
        } else {
            permission = dbPermission;
        }
        List<RolePermission> dbRolePermission = rolePermissionMapper.selectPermissionssByRidAndPids(rid, Lists.newArrayList(permission.getId()));
        if (CollectionUtils.isEmpty(dbRolePermission)) {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setCreateTime(now);
            rolePermission.setLastModifyTime(now);
            rolePermission.setCreator(creator);
            rolePermission.setLastModifier(creator);
            rolePermission.setRid(rid);
            rolePermission.setPid(permission.getId());
            rolePermission.insert();
        } else {
            for (RolePermission rolePermission : dbRolePermission) {
                rolePermissionMapper.updateByIdAndIsEnable(rolePermission.getId(), 1, now, creator);
            }
        }
        return permission.getId();
    }

    /**
     * 获取所有的可用角色 不可操作角色 disabled=true
     *
     * @param aid
     * @return
     */
    @Override
    public Map<String, List> getRoles(Long aid) {
        List<Long> value = new ArrayList<>();
        Admin admin = adminService.getAdminById(aid);
        if (Objects.nonNull(admin)) {
            admin = adminService.getAdminWithRoleAndPermission(admin);
        }
        List<String> roleCodes = admin.getRoles();
        List<Role> roles = new Role().selectAll();
        RoleRangeConverter roleRangeConverter = new RoleRangeConverter(admin.getLevel(), roleCodes);
        List<AuthoRangeVo> roleRangeVo = roleRangeConverter.toDtoList(roles);
        if (!CollectionUtils.isEmpty(roleRangeVo) && !CollectionUtils.isEmpty(roleCodes)) {
            value = roleRangeVo.stream().filter(vo -> roleCodes.contains(vo.getLabel())).distinct()
                    .map(AuthoRangeVo::getKey).collect(Collectors.toList());
        }
        return ImmutableMap.of("data", roleRangeVo, "value", value);
    }

    /**
     * 仅保留选中的角色
     *
     * @param aid
     * @param rids
     * @param admin
     */
    @Override
    @Transactional
    public void updateRole(Long aid, List<Long> rids, Admin admin) {
        Date now = new Date();
        if (!CollectionUtils.isEmpty(rids)) {
            List<AdminRole> adminRoles = adminRoleMapper.selectRolesByAid(aid);
            if (!CollectionUtils.isEmpty(adminRoles)) {
                for (AdminRole adminRole : adminRoles) {
                    if (rids.contains(adminRole.getRid())) {
                        if (adminRole.getIsEnable() == -1) {
                            adminRole.setIsEnable(1);
                            adminRoleMapper.updateByIdAndIsEnable(adminRole.getId(), adminRole.getIsEnable(), now,
                                    admin == null ? null : admin.getRealname());
                        }
                    } else {
                        adminRole.deleteById();
                    }
                }
            }
            //选中值中含有管理员没有的角色时新增
            List<Long> ridsInDB = adminRoles.stream().map(AdminRole::getRid).distinct().collect(Collectors.toList());
            List<Long> differenceRids = CommonUtil.getDifferences(rids, ridsInDB);
            if (!CollectionUtils.isEmpty(differenceRids)) {
                for (Long rid : differenceRids) {
                    AdminRole adminRole = new AdminRole();
                    adminRole.setAid(aid);
                    if (Objects.nonNull(admin)) {
                        adminRole.setCreator(admin.getRealname());
                        adminRole.setLastModifier(admin.getRealname());
                    }
                    adminRole.setCreateTime(now);
                    adminRole.setLastModifyTime(now);
                    adminRole.setRid(rid);
                    adminRole.insert();
                }
            }
        }
    }

    @Override
    public Map<String, List> getPermissions(Long aid) {
        List<Long> value = new ArrayList<>();
        Admin admin = adminService.getAdminById(aid);
        if (Objects.nonNull(admin)) {
            admin = adminService.getAdminWithRoleAndPermission(admin);
        }
        List<String> permissionCodes = admin.getPermissions();
        List<Permission> permissions = new Permission().selectAll();
        PermissionRangeConverter permissionConverter = new PermissionRangeConverter(admin.getLevel(), permissionCodes);
        List<AuthoRangeVo> permissionRangeVo = permissionConverter.toDtoList(permissions);
        if (!CollectionUtils.isEmpty(permissionRangeVo) && !CollectionUtils.isEmpty(permissionCodes)) {
            value = permissionRangeVo.stream().filter(vo -> permissionCodes.contains(vo.getLabel())).distinct()
                    .map(AuthoRangeVo::getKey).collect(Collectors.toList());
        }
        return ImmutableMap.of("data", permissionRangeVo, "value", value);
    }

    @Override
    @Transactional
    public void updatePermission(Long rid, List<Long> pids, Admin admin) throws Exception {
        Date now = new Date();
        if (!CollectionUtils.isEmpty(pids)) {
            List<RolePermission> rolePermissions = rolePermissionMapper.selectPermissionssByRidAndPids(rid, pids);
            if (!CollectionUtils.isEmpty(rolePermissions)) {
                for (RolePermission rolePermission : rolePermissions) {
                    if (pids.contains(rolePermission.getPid())) {
                        if (rolePermission.getIsEnable() == -1) {
                            rolePermission.setIsEnable(1);
                            rolePermissionMapper.updateByIdAndIsEnable(rolePermission.getId(), rolePermission.getIsEnable(), now,
                                    admin == null ? null : admin.getRealname());
                        } else {
                            rolePermission.deleteById();
                        }
                    }
                }
            }
            //选中值中含有角色没有的权限时新增
            List<Long> pidsInDB = rolePermissions.stream().map(RolePermission::getPid).distinct().collect(Collectors.toList());
            List<Long> differencePids = CommonUtil.getDifferences(pids, pidsInDB);
            if (!CollectionUtils.isEmpty(differencePids)) {
                for (Long pid : differencePids) {
                    RolePermission rolePermission = new RolePermission();
                    rolePermission.setRid(rid);
                    if (Objects.nonNull(admin)) {
                        rolePermission.setCreator(admin.getRealname());
                        rolePermission.setLastModifier(admin.getRealname());
                    }
                    rolePermission.setCreateTime(now);
                    rolePermission.setLastModifyTime(now);
                    rolePermission.setPid(pid);
                    rolePermission.insert();
                }
            }
        }
    }

    @Override
    public List<Role> getRolesByAid(Long aid) {
        List<AdminRole> adminRoles = new AdminRole().selectList(new EntityWrapper().eq("aid", aid));
        if (CollectionUtils.isEmpty(adminRoles)) {
            return Lists.newArrayList();
        }
        Set<Long> rids = adminRoles.stream()
                .map(AdminRole::getRid)
                .collect(Collectors.toSet());
        List<Role> roles = new Role().selectList(new EntityWrapper().in("id", rids));
        return CollectionUtils.isEmpty(roles) ? Lists.newArrayList() : roles;
    }

    @Override
    public List<Permission> getPermissionsByRids(Collection<Long> rids) {
        List<RolePermission> rolePermissions = new RolePermission().selectList(new EntityWrapper().in("rid", rids));
        if (CollectionUtils.isEmpty(rolePermissions)) {
            return Lists.newArrayList();
        }
        Set<Long> pids = rolePermissions.stream()
                .map(RolePermission::getPid)
                .collect(Collectors.toSet());
        List<Permission> permissions = new Permission().selectList(new EntityWrapper().in("id", pids));
        return CollectionUtils.isEmpty(permissions) ? Lists.newArrayList() : permissions;
    }
}